<?php
/**
 * 
 * @author	ronnie  (comdeng@gmail.com)
 * @link		http://fillphp.com/
 * @date		2014-5-3 下午2:11:27
 * @file		Blank.php
 * @description 
 */
namespace fillphp\helper;

class Blank extends \fillphp\helper\Helper
{
	const DEFAULT_BLANK_NAME = '__CONTENT__';
	const BLANK_START = '<script type="fillphp/fillview-blank">';
	const BLANK_END = '</script>';
	
	var $blanks = array();
	private $startBlanks = array();
	
	var $containerUri;
	
	/**
	 * 开始捕获内容
	 * @param string $name
	 * @throws Exception
	 */
	function start($name)
	{
		if (isset($this->startBlanks[$name])) {
			throw new Exception(__CLASS__.':blankHasStarted blank:'.$name);
		}
		$this->startBlanks[] = $name;

		ob_start();
		ob_implicit_flush(0);
	}
	
	/**
	 * 停止块内容的获取
	 * @throws \Exception
	 */
	function stop()
	{
		if (!$this->startBlanks) {
			throw new \Exception(__CLASS__.':blankNotStarted');
		}
		$name = array_pop($this->startBlanks);
		
		$this->blanks[$name] = ob_get_clean();
	}
	
	/**
	 * 获取块的内容
	 * @param string $name
	 * @param string $defValue
	 * @return string
	 */
	function get($name = self::DEFAULT_BLANK_NAME)
	{
		return self::BLANK_START.$name.self::BLANK_END;
	}
	
	/**
	 * 设置块的内容
	 * @param string $name
	 * @param string $value
	 */
	function set($name, $value)
	{
		$this->blanks[$name] = $value;
	}
	
	/**
	 * 将当前页面内容填充到指定页面
	 * @param string $uri
	 * @param array $blanks
	 * @param int $expire 缓存时间，单位为s，为0表示不缓存
	 */
	function fillTo($uri, $blanks = array(), $expire = 0)
	{
		if (is_int($blanks) && func_num_args() == 2) {
			$expire = $blanks;
			$blanks = array();
		}
		$this->containerUri = $uri;
		$this->blanks = array_replace($this->blanks, $blanks);
		
		// 增回调函数给view
		$self = $this;
		$this->view->addWrapper(function($content) use(&$self, $expire){
			$self->set(Blank::DEFAULT_BLANK_NAME, $content);
			return $self->fillBy($self->containerUri, $self->blanks, $expire);
		});
	}
	
	/**
	 * 用指定的网址填充当前位置
	 * @param string $url
	 * @param Array $blanks
	 * @param int $expire 缓存时间，单位为s，为0表示不缓存
	 * @return string
	 */
	function fillBy($uri, $blanks = array(), $expire = 0)
	{
		if (is_int($blanks) && func_num_args() == 2) {
			$expire = $blanks;
			$blanks = array();
		}
		$host = parse_url($uri, PHP_URL_HOST);
		if (!$host) {
			$request = $this->view->request;
			if (substr($uri, 0, 1) != '/') {
				$baseUrl = dirname($request->uri);
				$uri = $baseUrl.$uri;
			}
			$uri = 'http://'.$request->host.$uri;
		}
		
		// 获取缓存
		if ($expire > 0) {
			$cache = $this->view->fileCache();
			
			$content = $cache->get($uri, $expire);
			if ($content !== NULL) {
				return $this->fillBlanks($content, $blanks);
			}
		}
		
		require_once dirname(__DIR__).'/BlankDispatch.php';
		$dispatch = new \fillphp\BlankDispatch();
		
		$content = $dispatch->dispatch($uri);
		
		// 缓存改动
		if ($expire > 0) {
			$cache->set($uri, $content);
		}
		return $this->fillBlanks($content, $blanks);
	}
	
	/**
	 * 填充空白处
	 * @param string $content
	 * @param array $blanks
	 */
	private function fillBlanks($content, array $blanks)
	{
		if (!$blanks || !is_array($blanks)) return $content;
		$pos = mb_strpos($content, self::BLANK_START);
		$ret = '';
		$startLen = strlen(self::BLANK_START);
		$endLen = strlen(self::BLANK_END);
		while($content) {
			if ($pos === false) {
				$ret .= $content;
				break;
			}
			$ret .= mb_substr($content, 0, $pos);
			$end = mb_strpos($content, self::BLANK_END);
			if ($end === false) {
				$ret .= mb_substr($content, $pos);
				break;
			}
	
			$tag = mb_substr($content, $pos + $startLen, $end - $pos - $startLen);
			if (isset($blanks[$tag])) {
				$ret .= $blanks[$tag];
			}
	
			$content = mb_substr($content, $end + $endLen);
			$pos = mb_strpos($content, self::BLANK_START);
		}
		return $ret;
	}
}